
#include "../include/type.h"
#include "../include/server.h"

#define MAXEVENT 20
#define BUFFSIZE 100

int main(int argc,char **argv)
{
	int		                        server_port = -1;
	int		                        sockfd 	= -1;
	int		                        epollfd	= -1;
	int		                        rv 	= -1;
    int                             i;
    struct epoll_event              revent[MAXEVENT];
    char                            receive_buff[BUFFSIZE];
    char                            sendbuff[100];  
    pack_t                          parse_pack;
    int                             actnum = 0;

    pack_t                          response_pack;//响应包

    sqlite3                         *db;
	//参数解析
	server_port = argument_parse(argc, argv);
	if(server_port < 0)
	{
		return 0;
	}

	//套接字初始化
	sockfd = socket_init(server_port);
	if(sockfd < 0)
	{
		return 0;
	}

    //打开数据库
    rv = datbas_open(&db);
    if(rv < 0)
    {
        goto Cleanup;
    }

	//初始化epoll实例
	epollfd = epoll_init(sockfd);
    if(epollfd < 0)
    {
        close(sockfd);
        return 0;
    }

    printf("The initialization is complete and the server starts running...\n");

    while(1)
    {
        actnum = epoll_wait(epollfd,revent,MAXEVENT,-1);//-1:永远阻塞直到有文件描述被触发时返回
        if(actnum < 0)
        {
            printf("epoll_wait error:%s\n",strerror(errno));
            goto Cleanup;
        }
        //处理事件
        else
        {
            //遍历被触发的文件描述符
            for(i = 0; i < actnum; i++)
            {
                //处理新客户端
                if(revent[i].data.fd == sockfd)
                {
                    rv = accept_client(epollfd,sockfd);
                    if(rv < 0)
                    {
                        continue;//连接失败,继续处理下一个事件
                    }
                }
                //处理旧客户端
                else
                {
                    if(revent[i].events & EPOLLIN)
                    {
                        //接收数据
                        memset(receive_buff,0,sizeof(receive_buff));

                        //若数据报不完整,自动重新阻塞读取数据,2s之内没有读到完整数据报则返回,视为网络丢包
                        rv = receive_data(revent[i].data.fd,receive_buff,sizeof(receive_buff));
                        if(rv < 0)//出错
                        {
                            goto Cleanup;
                        }
                        else if(rv == TIMEOUT)//超时
                        {
                            printf("The server received a data timeout from client[%d], there may be packet loss!\n",revent[i].data.fd); 
                        }
                        else if(rv == UNLINK)//客户端断开
                        {
                            printf("The client[%d] has been disconnected!\n",revent[i].data.fd);
                            close(revent[i].data.fd);
                        }
                        else
                        { 
                            rv = pack_crc(receive_buff);//crc检验
                            if(rv == CRC_NO)
                            {
                                 printf("CRC vrified failly!\n");
                                 //向客户端发送NAK
                                 memset(&response_pack,0,sizeof(response_pack));
                                 strncpy(response_pack.nak,"CRC vrified failly!",sizeof(response_pack.nak));
                                 rv = tlv_pack(&response_pack,sendbuff,sizeof(sendbuff));
                                 if(rv > 0)
                                 {
                                     rv = write(revent[i].data.fd,sendbuff,rv+1);
                                     if(rv < 0)
                                     {
                                         printf("Server write error:%s\n",strerror(errno));
                                         goto Cleanup;
                                     }
                                 }

                            }
                            else
                            {
                                 printf("CRC vrified successfully! Will start unpacking!\n");
                                
                                 //开始解包
                                 memset(&parse_pack,0,sizeof(parse_pack));
                                 tlv_unpack(receive_buff, &parse_pack);//数据包解析


                                 //存入数据库
                                 if(!struct_is_empty(&parse_pack))
                                 {
                                     rv = datbas_insert(db,parse_pack.s_pack.date,parse_pack.s_pack.time,parse_pack.s_pack.sn,parse_pack.s_pack.temp);//存入数据库
                                     if(rv < 0)
                                     {
                                         goto Cleanup;
                                     }

                                     //向客户端发送ACK信息
                                     memset(&response_pack,0,sizeof(response_pack));
                                     strncpy(response_pack.ack,"The server successfully received and stored the data",sizeof(response_pack.ack));
                                     
                                     rv = tlv_pack(&response_pack,sendbuff,sizeof(sendbuff));
                                     if(rv > 0)
                                     {
                                         rv = write(revent[i].data.fd,sendbuff,rv+1);
                                         if(rv < 0)
                                         {
                                             printf("Server write error:%s\n",strerror(errno));
                                             goto Cleanup;
                                         }
                                     }
                                 }
                            }
                        }
                    

                    }
                }
            }


        }
    }
Cleanup:
    close(sockfd);
    datbas_close(db);
	return 0;
}
